<template>
    <div class="page_root" :key="queryUpdateFlag" data-page-name="1" data-page-identification="x_hb0xe6o0k2">
        <a-spin :spinning="pageLoading.loading" :tip="pageLoading.tip">
            <!-- begin vid_q2pj193dfc 自定义模板_7xu4mdl9mj -->
            <div style="display: flex; gap: 20px">
                <div style="flex: 1">
                    <h3 class="mg16">原始版本</h3>
                    <div v-html="leftDiffHtml" class="diff-box mg16"></div>
                </div>
                <div style="flex: 1">
                    <h3 class="mg16">最新版本</h3>
                    <div v-html="rightDiffHtml" class="diff-box"></div>
                </div>
            </div>
            <!-- end vid_q2pj193dfc 自定义模板_7xu4mdl9mj -->
        </a-spin>
    </div>
</template>
<script setup lang="tsx">
    import {
        h,
        ref,
        reactive,
        toRaw,
        markRaw,
        watch,
        computed,
        onBeforeMount,
        onMounted,
        onBeforeUnmount,
        onUnmounted,
        onActivated,
        onDeactivated
    } from 'vue'
    import { useRoute, useRouter } from 'vue-router'
    const router = useRouter()
    const route = useRoute()
    import { get, post, put, del, request, requestWithHeaders } from '@/utils/http/Axios'
    import {
        cloneDeep,
        localGet,
        merge,
        getDifferenceArray,
        traversalTreeStructure,
        checkCaseCondition,
        renderStringInTemplate,
        handleBreadcrumbJump,
        throttle,
        permission,
        getComponentParamsValue
    } from '@/utils'
    import { isNullOrEmpty, isEmptyArr, isNullOrUnDef, isContained, isArray, isEmpty, isObject } from '@/utils/is'
    import dayjs from 'dayjs'
    import { getPagePcChartsDataSourceConvert } from '@/utils/chart'
    import { message, notification, Modal } from 'ant-design-vue'
    import {
        propertyFormatByNumber,
        propertyFormatByPercentage,
        propertyFormatByDate,
        parseSubFromDataList
    } from '@/utils/format'
    import colorTheme from '@/design/custom-theme.json'
    /*** PUBLISH_EXEGESIS ***
 import UserTableRecords from '@/model/UserTableRecords';
 import { getAppBaseUrl } from '@/utils/index';
 import { sendToken } from "@/hooks/useIframeToken";
 import { useSystemStore } from "@/store/modules/system";
 const systemStore = useSystemStore();
 *** PUBLISH_EXEGESIS ***/

    // 获取传入的流程ID和组件参数
    const props = defineProps({
        'processInstanceId': {
            type: [String, Number, Boolean],
            default: undefined
        },
        'oldData': {
            type: [String],
            default: undefined
        },
        'newData': {
            type: [String],
            default: undefined
        }
    })
    const immediateWatch = (source, callback) => {
        watch(source, callback, { deep: true, immediate: true })
    }

    /* -------------------------- 属性定义 -------------------------- */

    const setTimeOutList = []
    const pageLoading = reactive({
        loading: false,
        tip: undefined
    })
    const authInfo = localGet('app-user-store')

    // 处理校验
    const setSubFormName = (parentInfo, name) => {
        return [parentInfo.parents, parentInfo.cycleIndex, name]
    }

    /* ========================== 属性定义 ========================== */

    /* -------------------------- 元素数据引用 -------------------------- */

    /* ========================== 元素数据引用 ========================== */

    /* -------------------------- 页面数据 -------------------------- */

    /* ========================== 页面数据 ========================== */

    /* -------------------------- 响应 -------------------------- */

    /* ========================== 响应 ========================== */

    /* -------------------------- 函数 -------------------------- */

    /* ========================== 函数 ========================== */

    /* -------------------------- 页面参数 -------------------------- */

    const pageParameter_state = reactive({
        'processInstanceId': props.processInstanceId ?? route.query.processInstanceId
    })

    /* ========================== 页面参数 ========================== */

    /* -------------------------- 组件事件处理方法 -------------------------- */

    // ---------------------------- 组件数据同步 ----------------------------

    // ============================ 组件数据同步 ============================

    /* ========================== 组件事件处理方法 ========================== */

    /* -------------------------- 生命周期 -------------------------- */
    // 用于参数变更后重新执行自定义指令
    const queryUpdateFlag = ref(0)
    onMounted(() => {})

    onUnmounted(() => {
        // 销毁定时器
        setTimeOutList.forEach(({ repeat, timer }) => {
            repeat ? clearInterval(timer) : clearTimeout(timer)
        })
    })

    /* ========================== 生命周期 ========================== */

    /* -------------------------- 数据关联处理 -------------------------- */

    /* -------------------------- 表单数据同步 -------------------------- */
    /* ========================== 表单数据同步 ========================== */

    /* ========================== 数据关联处理 ========================== */

    /* -------------------------- 不同组件自定义的处理逻辑 -------------------------- */

    /* ========================== 不同组件自定义的处理逻辑 ========================== */

    // ================================定制化逻辑========================================
    import { diff_match_patch } from 'diff-match-patch'
    import { watchEffect } from 'vue'
    const { oldData, newData } = props

    const dmp = new diff_match_patch()
    const diffs = ref([])

    const originalText = ref('')

    const updatedText = ref('')

    // 计算 diff 结果
    diffs.value = dmp.diff_main(originalText.value, updatedText.value)
    dmp.diff_cleanupSemantic(diffs.value)

    function getLineDiffs(orig, updated) {
        // 处理 undefined/null，确保 orig 和 updated 至少是空字符串
        orig = orig || ''
        updated = updated || ''

        // 如果传入的是非字符串（如数字），转换为字符串
        if (typeof orig !== 'string') orig = String(orig)
        if (typeof updated !== 'string') updated = String(updated)

        const origLines = orig.split('\n')
        const updatedLines = updated.split('\n')
        const maxLen = Math.max(origLines.length, updatedLines.length)
        const result = [] // 返回 [leftHtml, rightHtml, rowClass]

        for (let i = 0; i < maxLen; i++) {
            const o = origLines[i] ?? ''
            const u = updatedLines[i] ?? ''
            const diffs = dmp.diff_main(o, u)
            dmp.diff_cleanupSemantic(diffs)

            const leftParts = []
            const rightParts = []
            let hasChanges = false // 标记当前行是否有差异

            for (const [type, text] of diffs) {
                const safe = escapeHtml(text)
                if (type === 0) {
                    leftParts.push(safe)
                    rightParts.push(safe)
                } else {
                    hasChanges = true // 检测到差异
                    if (type === -1) {
                        leftParts.push(`<span class="delete">${safe}</span>`)
                    } else if (type === 1) {
                        rightParts.push(`<span class="insert">${safe}</span>`)
                    }
                }
            }

            // 如果有变化，添加 modified 类名；否则为空字符串
            const rowClass = hasChanges ? 'modified' : ''
            result.push([leftParts.join(''), rightParts.join(''), rowClass])
        }

        return result
    }
    const diffLines = computed(() => getLineDiffs(originalText.value, updatedText.value))
    const leftDiffHtml = computed(() =>
        diffLines.value
            .map(
                ([left, _, rowClass]) =>
                    `<div class="diff-line${rowClass ? ' ' + rowClass : ''}">${left || '&nbsp;'}</div>`
            )
            .join('')
    )

    const rightDiffHtml = computed(() =>
        diffLines.value
            .map(
                ([_, right, rowClass]) =>
                    `<div class="diff-line${rowClass ? ' ' + rowClass : ''}">${right || '&nbsp;'}</div>`
            )
            .join('')
    )
    // 防止 XSS
    function escapeHtml(text) {
        return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
    }
    watchEffect(() => {
        if (oldData || newData) {
            originalText.value = oldData
            updatedText.value = newData
            console.log('触发')
        }
    })
</script>
<style lang="less" scoped>
    .page_root {
        width: 100%;
        height: 100%;
        overflow: auto;
    }
    .page_root :deep(.@{ant-prefix}-spin-nested-loading),
    .page_root :deep(.@{ant-prefix}-spin-container) {
        height: 100%;
    }
    .page_root :deep(.@{ant-prefix}-spin-container .@{ant-prefix}-table-wrapper) {
        display: flex;
        flex-flow: column nowrap;
        justify-content: flex-start;
    }
    .page_root :deep(.@{ant-prefix}-table) {
        flex: auto;
        overflow: auto;
    }
    .table-moreBtn_down {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        width: 100px;
    }

    .table-moreBtn_menu :deep(.table-moreBtn_menu-item):hover {
        background: #ebf1ff;
    }

    /*  表格树结构样式处理，展开按钮层级增加*/
    :deep(.@{ant-prefix}-table-row-expand-icon) {
        z-index: 1;
    }
    /*  表格树结构 由于每个表格项采用自定义组件，使用绝对定位布局，开启树结构导致显示异常，暂时使用层级定位位置 */
    :deep(.@{ant-prefix}-table-row-level-1 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 15px !important;
        width: calc(100% - 15px);
    }
    :deep(.@{ant-prefix}-table-row-level-2 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 30px !important;
        width: calc(100% - 30px);
    }
    :deep(.@{ant-prefix}-table-row-level-3 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 45px !important;
        width: calc(100% - 45px);
    }
    :deep(.@{ant-prefix}-table-row-level-4 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 60px !important;
        width: calc(100% - 60px);
    }

    /* 穿梭框改变默认样式，为根据组件样式控制左右栏宽度。 */
    :deep(.@{ant-prefix}-transfer-list) {
        height: 100%;
        width: 50%;
    }
    :deep(.diff-box) {
        border: 1px solid #ccc;
        padding: 10px;
        white-space: pre-wrap;
        font-family: monospace;
        background-color: #f9f9f9;
        border-radius: 4px;
        color: #262626;
    }
    :deep(.delete) {
        background-color: #ffd6d6; /* 更深的删除背景 */
        color: #ff2a00;
        text-decoration: line-through;
    }
    :deep(.insert) {
        background-color: #c8facc; /* 更深的插入背景 */
        color: #30bf78;
    }
    :deep(.modified) {
        background: rgba(56, 117, 255, 0.1);
        border-left: 2px solid #3875ff; // 左侧黄色边框
        margin: 2px 0;
        padding: 2px 5px;
    }
    .mg16 {
        //margin-bottom: 16px;
    }
</style>
